{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 200,
   "metadata": {},
   "outputs": [],
   "source": [
    "import pandas as pd\n",
    "import pandas_datareader.data as web\n",
    "import numpy as np"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 202,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>AMZN</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Date</th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>2019-05-13</th>\n",
       "      <td>1822.680054</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2019-05-14</th>\n",
       "      <td>1840.119995</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2019-05-15</th>\n",
       "      <td>1871.150024</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2019-05-16</th>\n",
       "      <td>1907.569946</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2019-05-17</th>\n",
       "      <td>1869.000000</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                   AMZN\n",
       "Date                   \n",
       "2019-05-13  1822.680054\n",
       "2019-05-14  1840.119995\n",
       "2019-05-15  1871.150024\n",
       "2019-05-16  1907.569946\n",
       "2019-05-17  1869.000000"
      ]
     },
     "execution_count": 202,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "availStocks = ['AMZN']#, 'AAPL']\n",
    "stocks = availStocks\n",
    "\n",
    "numAssets = len(stocks)\n",
    "source = 'yahoo'\n",
    "start = '2019-05-13'\n",
    "end = '2020-03-10'\n",
    "\n",
    "data = pd.DataFrame()\n",
    "\n",
    "for stock in stocks:\n",
    "  data[stock] = web.DataReader(stock,data_source=source,start=start,end=end)['Adj Close']\n",
    "\n",
    "data.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 197,
   "metadata": {},
   "outputs": [],
   "source": [
    "class RiskCalc():\n",
    "    def __init__(self, returns):\n",
    "        self.returns = returns\n",
    "        '''\n",
    "        Asset returns can be passed as a pandas DataFrame.\n",
    "        Each column represents the price returns of a given asset.\n",
    "        \n",
    "                AAPL         AMZN\n",
    "        Date\n",
    "        2015-01-02  NaN       NaN\n",
    "        2015-01-05  -0.028172 -0.020517\n",
    "        2015-01-06  0.000094  -0.022833\n",
    "        2015-01-07  0.014022  0.010600\n",
    "        '''\n",
    "\n",
    "    def cov(self, frequency=252): # Volatility measure\n",
    "        cov_matrix = self.returns.cov() * frequency\n",
    "        return cov_matrix\n",
    "\n",
    "\n",
    "    def semicov(self, frequency=252, benchmark=0):\n",
    "        '''\n",
    "        Substract benchmark from returns and return the minimum of 0 or subtracted returns.\n",
    "        The function can be used to return the covariance of the downside risk price changes by using a benchmark=0.\n",
    "        '''\n",
    "        down_returns = np.fmin(self.returns - benchmark, 0)\n",
    "        down_cov_matrix = down_returns.cov() * frequency\n",
    "        return down_cov_matrix\n",
    "\n",
    "    \n",
    "    def beta(benchmark_returns): # Volatility measure\n",
    "        \"\"\"\n",
    "        Calculates the beta of an asset/porfolio in comparision to a benchmark given it's returns.\n",
    "        The benchmark is usually the market e.g. S&P 500.\n",
    "        \n",
    "        Beta measures the relationship between the security returns,  and the market.\n",
    "        High beta stocks are considered to be more risk whereas low beta stocks are considered to be less risky.\n",
    "\n",
    "        Parameters\n",
    "        ----------\n",
    "        benchmark_returns : numpy.array or pandas.DataFrame\n",
    "        Price returns of benchmark/market over a period of time e.g daily returns\n",
    "    \n",
    "        Returns\n",
    "        ----------\n",
    "        beta : float\n",
    "        \"\"\"\n",
    "        matrix = np.matrix(self.returns, benchmark_returns)\n",
    "        cov_matrix = np.cov(matrix)\n",
    "        beta = cov_matrix[0][1]/np.sqrt(cov_matrix[1][1])\n",
    "        return beta\n",
    "\n",
    "\n",
    "    def lpm(threshold, order):\n",
    "        '''\n",
    "        Calculate the lower partial moment given an asset's returns.\n",
    "        \n",
    "        The larger the order of lpm the greater the weighting will be on returns that fall below the \n",
    "        target threshold, meaning that larger orders result in more risk-averse measures.\n",
    "        Changing the order (weighting coefficient) of lpm leads to the following interpretations.\n",
    "\n",
    "        Parameters\n",
    "        ----------   \n",
    "        threshold : float\n",
    "        Minimum return of which the return deviation is measured. Standard value is the risk-free rate.\n",
    "        \n",
    "        order : int\n",
    "        Order = 0, Probability of loss\n",
    "        Order = 1, Expected loss\n",
    "        Order = 2, Semi-Variance of returns\n",
    "        '''\n",
    "        #Difference between threshold and returns, set each negative difference to 0.\n",
    "        lower = (threshhold - self.returns).clip(lower=0)\n",
    "        return (lower ** order).sum() / len(self.returns)\n",
    "    \n",
    "    \n",
    "    def hpm(threshold, order):\n",
    "        higher = (self.returns - threshhold).clip(lower=0)\n",
    "        return (lower ** order).sum() / len(self.returns)\n",
    "    \n",
    "\n",
    "    def max_dd(returns):\n",
    "        cum_r = returns.add(1).cumprod()\n",
    "        cum_r.plot()\n",
    "        drawdowns = cum_r.div(cum_r.cummax()).sub(1)\n",
    "        mdd = drawdowns.min()\n",
    "        return mdd\n",
    "\n",
    "    \n",
    "    def avg_dd(returns, periode):\n",
    "        cum_r = returns.add(1).cumprod()\n",
    "        drawdowns = cum_r.div(cum_r.cummax()).sub(1)\n",
    "        avg = drawdowns.sum() / periode\n",
    "        return avg\n",
    "    \n",
    "    \n",
    "    def avg_dd_squared(returns, periode):\n",
    "        cum_r = returns.add(1).cumprod()\n",
    "        drawdowns = cum_r.div(cum_r.cummax()).sub(1) ** 2\n",
    "        avg = drawdowns.sum() / periode\n",
    "        return avg"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 203,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>AMZN</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>AMZN</th>\n",
       "      <td>10636.281099</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "              AMZN\n",
       "AMZN  10636.281099"
      ]
     },
     "execution_count": 203,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "cov = data.cov()\n",
    "cov"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def sharpe_ratio(returns, rf):\n",
    "    return (returns - rf) / vol(returns)\n",
    "\n",
    "\n",
    "def treynor_ratio(er, returns, market, rf):\n",
    "    return (er - rf) / beta(returns, market)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
